//
//  myController.m
//  iListTest
//
//  Created by Ronnie on 08-10-18.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "ListController.h"
#import "SimpleTreeNode.h"
#import "MyCell.h"
#import "FXToolTipController.h"
#import "DialogWindowController.h"
#import "MainAppController.h"

// ================================================================
// Useful Macros
// ================================================================
#define INITIAL_INFODICT	@"InitInfo"
#define COLUMNID_NAME		@"TreeColumn"

// Conveniences for accessing nodes, or the data in the node.
#define FXNODE(n)			((FXTreeNode*)n)
#define SAFEFXNODE(n) 		((FXTreeNode*)((n)?(n):(buddyList)))

@implementation ListController
- (id) init
{
	self = [super init];
	if (self != nil) {
		dialogWindowController = nil;
		addBuddyCtrl = nil;
	}
	return self;
}


- (void)dealloc
{
	if (dialogWindowController) {
		[dialogWindowController release];
	}
	if (buddyList) {
		[buddyList release];
	}
	if (myFetionData) {
		[myFetionData release];
	}
	if (mainAppCtrl) {
		[mainAppCtrl release];
	}
	if (dialogWindowController) {
		[dialogWindowController release];
	}
	if (addBuddyCtrl) {
		[addBuddyCtrl release];
	}
    [super dealloc];
}

- (void)awakeFromNib
{
    // Insert custom cell types into the table view, the standard one does text only.
    // We want one column to have text and images, and one to have check boxes.
    //
	NSTableColumn* tableColumn = [outlineView tableColumnWithIdentifier: COLUMNID_NAME];
	
    MyCell* myCell = [[[MyCell alloc] init] autorelease];
    [myCell setEditable: YES];
    [tableColumn setDataCell:myCell];
	
	[outlineView setIgnoresMultiClick:YES];
	[outlineView setTarget:self];
	[outlineView setAction:@selector(onClick:)];
	[outlineView setDoubleAction:@selector(onDoubleClick:)];
	
	[self addNotificationResponser];
	[[outlineView menu] setDelegate:self];

	addBuddyCtrl = [[addBuddyWindow delegate] retain];
	
	fxToolTipCtrl = [[FXToolTipController alloc] initWithView:outlineView];
	//[fxToolTipCtrl showWindow:nil];
	
}

- (void)loadGroupNamesForMenu
{
	NSMenu* contextMenu = [outlineView menu];
	NSMenu* subMenu = [[contextMenu itemAtIndex:4] submenu];
	if ([subMenu numberOfItems] > 0) {
		while([subMenu numberOfItems]!=0)
		{
			[subMenu removeItemAtIndex:[subMenu numberOfItems]-1];
		}
		/*for (int i=0; i<[subMenu numberOfItems]; i++) {
			[subMenu removeItemAtIndex:i];
		}*/
	}
	for (int i=0; i<[buddyList numberOfChildren]; i++) {
		FXTreeNode* groupNode = [buddyList childAtIndex:i];
		if ([groupNode isGroup]) {
			NSMenuItem *item = [[NSMenuItem alloc] init];
			[item setTitle:[groupNode getGroupName]];
			[item setTag:[groupNode groupId]];
			[item setTarget:self];
			[item setAction:@selector(onMoveGroupBuddy:)];
			[subMenu addItem:item];
			[item release];
		}
	}
}

- (IBAction)onShowAccountInfo:(id)sender
{
	NSInteger clickedRow = [outlineView clickedRow];
	FXTreeNode* node = [[outlineView itemAtRow:clickedRow] retain];
	
	FXAccountInfoController* infoPanel = [[FXAccountInfoController alloc] init];
	[infoPanel showWindow:self];
	[infoPanel setAccountInfo:[node getUserInfo]];
	
	//[infoPanel autorelease];
}


- (IBAction)onMoveGroupBuddy:(id)sender
{
	NSInteger clickedRow = [outlineView clickedRow];
	FXTreeNode* node = [[outlineView itemAtRow:clickedRow] retain];
	NSMenuItem* clickedMenu = (NSMenuItem*)sender;
	
	int groupId = [clickedMenu tag];
	
	fx_move_group_buddy_by_id([[node getUserInfo] userID], groupId, NULL, NULL);
	
	[node release];
}

- (void)moveGroupOKWith:(FXSysMessage*)sysMessage
{
	NSLog(@"List Move Group!");
	[sysMessage retain];
	long uid = (long)[sysMessage getLParam];
	int groupId = (int)[sysMessage getWParam];
	
	FXTreeNode* node = [myFetionData getFXTreeNodeById:uid];
	FXTreeNode* parent = [node getNodeParent];
	FXTreeNode* newParent = [myFetionData getGroupNodeById:groupId];
	
	[parent removeChild:node];
	[newParent insertChild:node atIndex:[newParent numberOfChildren]];
	[[node getUserInfo] setUserGroupId:groupId];
	[newParent recursiveSortChildren];
	
	NSLog(@"Scroll List");
	[outlineView reloadData];
	NSInteger newRow = [outlineView rowForItem:node];
	[outlineView selectRow:newRow byExtendingSelection:NO];
	[outlineView scrollRowToVisible:newRow];	
	
	[sysMessage release];
}


- (IBAction)onAddOrRemoveBlackList:(id)sender
{
	NSInteger clickedRow = [outlineView clickedRow];
	FXTreeNode* node = [[outlineView itemAtRow:clickedRow] retain];
	if ([[node getUserInfo] isInBlackList]) {
		fx_removefrom_blacklist_by_id([[node getUserInfo] userID], nil, nil);
	}	
	else {
		fx_addto_blacklist_by_id([[node getUserInfo] userID], nil, nil);
	}
	
	[node release];
}

- (IBAction)onDeleteBuddy:(id)sender
{
	NSInteger clickedRow = [outlineView clickedRow];
	FXTreeNode* node = [[outlineView itemAtRow:clickedRow] retain];
	
	fx_delete_buddy_by_id([[node getUserInfo] userID], nil, nil);
	
	[node release];
}

- (IBAction)onDeleteGroup:(id)sender
{
	NSInteger clickedRow = [outlineView clickedRow];
	FXTreeNode* node = [[outlineView itemAtRow:clickedRow] retain];
	
	fx_delete_buddylist([node groupId], nil, nil);
	
	[node release];
}


- (IBAction)onClick:(id)sender
{
	int row = [outlineView selectedRow];
	if(row == -1)
		return;
	FXTreeNode* obj = [outlineView itemAtRow:row];
	
	[outlineView reloadData];
	
	NSLog(@"Class of Obj is %@", [obj class]);
	if ([SAFEFXNODE(obj) isGroup]) {
		
		if ([outlineView isItemExpanded:obj]) {
			[outlineView collapseItem:obj];
		}
		else {
			[outlineView expandItem:obj];
		}
	}
}


- (IBAction)onDoubleClick:(id)sender
{
	int row = [outlineView selectedRow];
	if(row == -1)
		return;
	FXTreeNode* obj = [outlineView itemAtRow:row];
	
	[outlineView reloadData];
	
	NSLog(@"Class of Obj is %@", [obj class]);
	if ([SAFEFXNODE(obj) isGroup]) {
		
		if ([outlineView isItemExpanded:obj]) {
			[outlineView collapseItem:obj];
		}
		else {
			[outlineView expandItem:obj];
		}
		
	}
	else
	{
		if ([[obj getUserInfo] userState] == FX_STATUS_WAITING_AUTH) {
			NSLog(@"Not Authorized");
		}
		else
		{
			NSLog(@"open chat");
			if (![obj getDialogWindowContorller]) {
				NSLog(@"NOT Exist window");
				DialogWindowController* dialogWindowCtrl = [[DialogWindowController alloc] init];
				[obj setDialogWindowController:dialogWindowCtrl];
				[[obj getDialogWindowContorller] showWindow:self];
				[[obj getDialogWindowContorller] setChatFriendData:obj];
				[dialogWindowCtrl release];
			}
			else
				[[obj getDialogWindowContorller] showWindow:self];
			NSLog(@"out open chat");
		}
	}
	
}

- (void)setMainWindowController:(MainWindowController*)p
{
	mainWindowCtrl = [p retain];
	[addBuddyCtrl setMainWindowController:mainWindowCtrl];
}

- (void)setMainAppController:(MainAppController*)p
{
	mainAppCtrl = [p retain];
	myFetionData = [[mainAppCtrl getFxData] retain];
	buddyList = [[myFetionData getMyBuddyList] retain];
	
	[self loadGroupNamesForMenu];
	[addBuddyCtrl setMainAppController:mainAppCtrl];
}


- (void)changStageById:(FXSysMessage*)sysMessage
{
	//[myFetionData updateInfoById:[[node getUserInfo] userID]];
	//[[mainWindowController getListController] reloadItem:node];
	@synchronized(self)
	{
		long uid = (long)[sysMessage getLParam];
		
		FXTreeNode* node = [myFetionData getFXTreeNodeById:uid];
		[[node getUserInfo] updateSelfInfo];
		[[node getNodeParent] recursiveSortChildren];
		[outlineView reloadData];
	
		NSInteger newRow = [outlineView rowForItem:node];
		[outlineView selectRow:newRow byExtendingSelection:NO];
		[outlineView scrollRowToVisible:newRow];
		
		[[node getDialogWindowContorller] reloadFriendStatur];
	}
}

- (void)changeUserLocalName:(FXSysMessage*)sysMessage
{
	[sysMessage retain];
	long uid = (long)[sysMessage getLParam];
	
	FXTreeNode* node = [myFetionData getFXTreeNodeById:uid];
	[[node getUserInfo] updateUserName];
	[[node getNodeParent] recursiveSortChildren];
	[outlineView reloadData];
	
	NSInteger newRow = [outlineView rowForItem:node];
	[outlineView selectRow:newRow byExtendingSelection:NO];
	[outlineView scrollRowToVisible:newRow];
	
	[sysMessage release];
}


- (void)changeGroupName:(FXSysMessage*)sysMessage
{
	[sysMessage retain];
	int groupId = (int)[sysMessage getWParam];
	
	FXTreeNode* node = [myFetionData getGroupNodeById:groupId];
	[node updateGroupName];
	
	[outlineView reloadItem:node];

	[sysMessage release];
	
}

- (void)deleteBuddy:(FXSysMessage*)sysMessage
{
	[sysMessage retain];
	long uid = (long)[sysMessage getLParam];
	
	FXTreeNode* node = [myFetionData getFXTreeNodeById:uid];
	[[node getNodeParent] removeChild:node];
	[outlineView reloadData];
	
	[sysMessage release];
}

- (void)deleteGroup:(FXSysMessage*)sysMessage
{
	[sysMessage retain];
	int groupId = (int)[sysMessage getWParam];
	
	FXTreeNode* node = [myFetionData getGroupNodeById:groupId];
	[[node getNodeParent] removeChild:node];
	[outlineView reloadData];
	
	[self loadGroupNamesForMenu];
	
	[sysMessage release];
}

- (void)addGroup:(FXSysMessage*)sysMessage
{
	[sysMessage retain];
	int groupId = (int)[sysMessage getWParam];
	
	[myFetionData addGroupById:groupId];
	
	[outlineView reloadData];
	
	[self loadGroupNamesForMenu];
	
	[sysMessage release];
}

- (void)addBuddy:(FXSysMessage*)sysMessage
{
	[sysMessage retain];
	@synchronized(self)
	{
		long uid = (long)[sysMessage getLParam];
		int groupId = (int)[sysMessage getWParam];
	
		[myFetionData addBuddy:uid toGroup:groupId];
		
		[outlineView reloadData];
		
		[myFetionData PrintBuddyList];
	}
	[sysMessage release];
}

// ================================================================
//  NSOutlineView data source methods. (The required ones)
// ================================================================

// Required methods.
- (id)outlineView:(NSOutlineView*)olv child:(int)index ofItem:(id)item
{
	return [SAFEFXNODE(item) childAtIndex:index];
}

- (BOOL)outlineView:(NSOutlineView*)olv isItemExpandable:(id)item
{
    return [SAFEFXNODE(item) isGroup];
}

- (int)outlineView:(NSOutlineView*)olv numberOfChildrenOfItem:(id)item
{
	int result = [SAFEFXNODE(item) numberOfChildren];
	return result;
}

- (id)outlineView:(NSOutlineView*)olv objectValueForTableColumn:(NSTableColumn*)tableColumn byItem:(id)item
{
    id objectValue = nil;
    
    // The return value from this method is used to configure the state of the items cell via setObjectValue:
    if([[tableColumn identifier] isEqualToString: COLUMNID_NAME])
	{
		objectValue = SAFEFXNODE(item);
    }
	return objectValue;
}
- (void)outlineView:(NSOutlineView *)olv setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item  
{
	
}

// ================================================================
//  NSOutlineView delegate methods.
// ================================================================

- (BOOL)outlineView:(NSOutlineView*)olv isGroupItem:(id)item {
    return [SAFEFXNODE(item) isGroup];
}

- (BOOL)outlineView:(NSOutlineView*)olv shouldExpandItem:(id)item
{
    return [SAFEFXNODE(item) isExpandable];
}


- (CGFloat)outlineView:(NSOutlineView *)olv heightOfRowByItem:(id)item
{
	if ([SAFEFXNODE(item) isGroup]) {
		return 16.0f;
	}
	else
		return 28.0f;
}

#pragma mark notification responser
- (void)addNotificationResponser
{
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(reloadData:)
												 name:@"FETION_STATUS_CHANGES" object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self
											 selector:@selector(reStoreTooltipTrackingArea:)
												 name:@"MAIN_WINDOW_RESIZE" object:nil];
}


- (void)reloadData:(NSNotification*)notification
{
	NSLog(@"need reload data!");
	[outlineView reloadData];
}

- (void)reStoreTooltipTrackingArea:(NSNotification*)notification
{
	if (fxToolTipCtrl) {
		[fxToolTipCtrl storeTrackingArea];
	}
}

- (void)reloadItem:(id)item
{
	NSLog(@"Need reload item");
	[outlineView reloadItem:item];
}

#pragma mark menu degelate

- (void)menuNeedsUpdate:(NSMenu *)menu 
{
	int selectedRow = [outlineView selectedRow];
	NSInteger clickedRow = [outlineView clickedRow];
	
	[outlineView selectRow:clickedRow byExtendingSelection:NO];
	FXTreeNode* node = [outlineView itemAtRow:clickedRow];
	
	// change the menu according to node
	if ([node isLeaf]) {
		NSMenuItem* item = [[outlineView menu] itemAtIndex:0];
		[item setTarget:self];
		[item setAction:@selector(onDoubleClick:)];
		[item setEnabled:YES];
		item = [[outlineView menu] itemAtIndex:1];
		[item setTarget:self];
		[item setAction:@selector(onShowAccountInfo:)];
		[item setEnabled:YES];
		item = [[outlineView menu] itemAtIndex:2];
		[item setTitle:@"Change Local Name"];
		item = [[outlineView menu] itemAtIndex:4];
		[item setEnabled:YES];
		item = [[outlineView menu] itemAtIndex:6];
		if ([[node getUserInfo] isInBlackList])
			[item setTitle:@"Remove from black list"];
		else
			[item setTitle:@"Add to black list"];
		[item setEnabled:YES];
		item = [[outlineView menu] itemAtIndex:7];
		[item setTitle:@"Add Buudy"];
		[item setEnabled:NO];
		item = [[outlineView menu] itemAtIndex:8];
		[item setTitle:@"Delete Buddy"];
		[item setTarget:self];
		[item setAction:@selector(onDeleteBuddy:)];
		[item setEnabled:YES];
	}
	else if ([node isGroup]) {
		NSMenuItem* item = [[outlineView menu] itemAtIndex:0];
		[item setAction:nil];
		[item setEnabled:NO];
		item = [[outlineView menu] itemAtIndex:1];
		[item setAction:nil];
		[item setEnabled:NO];
		item = [[outlineView menu] itemAtIndex:2];
		[item setTitle:@"Change Group Name"];
		item = [[outlineView menu] itemAtIndex:4];
		[item setEnabled:NO];
		item = [[outlineView menu] itemAtIndex:6];
		[item setTitle:@"Add to black list"];
		[item setEnabled:NO];
		item = [[outlineView menu] itemAtIndex:7];
		[item setTitle:@"Add Group"];
		[item setEnabled:YES];
		[item setTarget:self];
		[item setAction:@selector(showAddGroupInputNameSheet:)];
		item = [[outlineView menu] itemAtIndex:8];
		[item setTitle:@"Delete Group"];
		if ([node numberOfChildren]==0)
		{
			[item setEnabled:YES];
			[item setTarget:self];
			[item setAction:@selector(onDeleteGroup:)];
		}
		else
		{
			[item setAction:nil];
			[item setEnabled:NO];
		}
	}
}

/*- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
{
	int selectedRow = [outlineView selectedRow];
	NSLog(@"%i", selectedRow);
	return TRUE;
}*/

#pragma mark method for sheet
- (IBAction)showChangeNameSheet:(id)sender
{
	NSInteger clickedRow = [outlineView clickedRow];
	FXTreeNode* node = [[outlineView itemAtRow:clickedRow] retain];
	[NSApp beginSheet:changeNameWindow modalForWindow:[mainWindowCtrl window] modalDelegate:self didEndSelector:@selector(changeName:returnCode:context:) contextInfo:node];
}

- (IBAction)endChangeNameSheet:(id)sender
{
	[NSApp endSheet:changeNameWindow returnCode:[(NSButton*)sender tag]];
	[changeNameWindow orderOut:sender];
}

- (void)changeName:(NSWindow *)sheet returnCode:(int)returnCode context:(void *)contextInfo
{
	if ( returnCode==1 ) {
		
		FXTreeNode* node = (FXTreeNode*)contextInfo;
		if ([node isLeaf]) {
			NSLog(@"leaf change name to %@, and tag is %i", [textField stringValue], returnCode);
			fx_set_buddyinfo([[node getUserInfo] userID], [[textField stringValue] UTF8String], NULL, NULL);
		}
		else if ([node isGroup]) {
			NSLog(@"Group change name to %@, and tag is %i", [textField stringValue], returnCode);
			fx_rename_buddylist([node groupId], [[textField stringValue] UTF8String], NULL, NULL);
		}
	}
}

- (IBAction)showAddGroupInputNameSheet:(id)sender
{
	[NSApp beginSheet:changeNameWindow modalForWindow:[mainWindowCtrl window] modalDelegate:self didEndSelector:@selector(AddGroupByName:returnCode:context:) contextInfo:nil];
}
- (void)AddGroupByName:(NSWindow *)sheet returnCode:(int)returnCode context:(void *)contextInfo
{
	if ( returnCode==1 ) {
		NSLog(@"Add group by name %@", [textField stringValue]);
		fx_add_buddylist([[textField stringValue] UTF8String], nil, nil);
	}
}

- (IBAction)showAddBuddySheet:(id)sender
{
	[NSApp beginSheet:addBuddyWindow modalForWindow:[mainWindowCtrl window] modalDelegate:self didEndSelector:@selector(AddBuddy:returnCode:context:) contextInfo:nil];
}
- (IBAction)endAddBuddySheet:(id)sender
{
	[NSApp endSheet:addBuddyWindow returnCode:[(NSButton*)sender tag]];
	[addBuddyWindow orderOut:sender];
}
- (void)AddBuddy:(NSWindow *)sheet returnCode:(int)returnCode context:(void *)contextInfo
{
	if ( returnCode==1 ) {
		NSLog(@"Add Buddy");
		[addBuddyCtrl sendAddBuddyRequest];
		//fx_add_buddylist([[textField stringValue] UTF8String], nil, nil);
	}
}

//- (void)mouseEntered:(NSEvent *)theEvent {
//	NSLog(@"Mouse Entered");
//}
//
//- (void)mouseExited:(NSEvent *)theEvent {
//	NSLog(@"Mouse Exited");
//}

@end
